package com.dataaccess.dataaccess.support.tcp;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.dataaccess.dataaccess.config.rocketmq.UserProducer;
import com.dataaccess.dataaccess.support.utils.ByteUtil;
import com.dataaccess.dataaccess.web.mapper.AutoNetworkAlarmDeviceDataChangedMapper;
import com.dataaccess.dataaccess.web.service.AutoNetworkAlarmDeviceDataChangedService;
import lombok.SneakyThrows;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Hashtable;

/**
 * @Author: YangYu
 * @ClassName: GST200
 * @Date: Created in 14:15 2021/5/17
 * @Description:
 */
@Component
public class SiTerWell {
    private static final int SERVER_PORT = 13;

    private static Hashtable<String, Socket> ht = new Hashtable();

    private static Hashtable<String, String> strHt = new Hashtable();


    @Resource
    UserProducer userProducer;
    @Resource
    private AutoNetworkAlarmDeviceDataChangedMapper autoNetworkAlarmDeviceDataChangedMapper;
    @Resource
    private AutoNetworkAlarmDeviceDataChangedService autoNetworkAlarmDeviceDataChangedService;

    @Async
    public void server() throws IOException {
        // TODO Auto-generated method stub
        System.out.println("VNTCenter.main()===TCP SERVER==============");
        ServerSocket vntServer = null;
        try {
            vntServer = new ServerSocket(SERVER_PORT);
            //System.out.println(11+"-----------------------------");
            System.out.println("Listening Port is " + vntServer.getLocalPort() + "...");
            while (true) {
                Socket vntClient = vntServer.accept();
                //当调用socket.getInputStream().read()方法时,由于这个read()方法是阻塞的,read()方法会一直处于阻塞状态等待接受数据而导致不能往下执行代码;而setSoTimeout()方法就是设置阻塞的超时时间.
                //超时后的客户端需要重新连接
                System.out.println("have a client entering , the IP is " + vntClient.getInetAddress() + "...");
                System.out.println("have a client entering , the Port is " + vntClient.getPort() + "...");
                new GetGstThreadFun(vntClient, ht,strHt, userProducer, autoNetworkAlarmDeviceDataChangedMapper, autoNetworkAlarmDeviceDataChangedService).start();
            }
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            vntServer.close();
        }
    }
}

class GetGstThreadFun extends Thread {
    private Socket vntThreadClient;
    UserProducer userProducer;
    private Hashtable<String, Socket> ht = new Hashtable();
    private Hashtable<String, String> strHt = new Hashtable();
    OutputStream os = null;
    AutoNetworkAlarmDeviceDataChangedService autoNetworkAlarmDeviceDataChangedService;
    @Resource
    private AutoNetworkAlarmDeviceDataChangedMapper autoNetworkAlarmDeviceDataChangedMapper;

    public GetGstThreadFun(Socket vntThreadSocket, Hashtable<String, Socket> ht,Hashtable<String, String> strHt, UserProducer userProducer,
                           AutoNetworkAlarmDeviceDataChangedMapper autoNetworkAlarmDeviceDataChangedMapper,
                           AutoNetworkAlarmDeviceDataChangedService autoNetworkAlarmDeviceDataChangedService) {
        this.vntThreadClient = vntThreadSocket;
        this.userProducer = userProducer;
        this.autoNetworkAlarmDeviceDataChangedMapper = autoNetworkAlarmDeviceDataChangedMapper;
        this.autoNetworkAlarmDeviceDataChangedService = autoNetworkAlarmDeviceDataChangedService;
        this.ht = ht;
        this.strHt = strHt;
    }

    @SneakyThrows
    @Override
    public void run() {
        try {
            byte[] data = new byte[128];
            while (true) {
                //vntThreadClient.setSoTimeout(10000);
                int len = vntThreadClient.getInputStream().read(data);
                if (len > 0) {
                    System.out.println(vntThreadClient.getInetAddress() + ":" + vntThreadClient.getPort() + ":" + new String(data, 0, len, "gbk"));
                    os = vntThreadClient.getOutputStream();   //输出流
                    String ss = ByteUtil.BinaryToHexString(data, 0, len).replace(" ", "");
                    System.out.println(ss);
                    System.out.println(String.valueOf(data));
                    //返回指令
                    String returnCode = "FE0403EE000885B2";
                    if (StrUtil.isBlank(ss) || ss.length() < 6 || ss.substring(0, 3).equals("138") || ss.substring(0, 4).equals("3A31") ){

                    }else if (ss.substring(0, 6).equals("FE0410") || ss.substring(0, 4).equals("FE05")) {
                        //设备号
                        String number = convertHexToString(ss.substring(6,38));
                        returnCode = "FE010000000429C6";
                        ht.put(number,vntThreadClient);
                        strHt.put(vntThreadClient.getInetAddress()+"-"+vntThreadClient.getPort(),number);
                    }else if (ss.substring(0, 6).equals("FE0101")){//四路状态
                        String str = Integer.toBinaryString(Integer.parseInt(ss.substring(6, 8), 16));
                        String number = strHt.get(vntThreadClient.getInetAddress()+"-"+vntThreadClient.getPort());
                        System.out.println("设备号："+number);
                        if(str.length() == 1){
                            str = "000" + str;
                        }else if(str.length() == 2){
                            str = "00" + str;
                        }else if(str.length() == 3){
                            str = "0" + str;
                        }
                        if (str.charAt(3) == '1'){
                            System.out.println("第一路开");
                        }else if (str.charAt(2) == '1'){
                            System.out.println("第二路开");
                        }else if (str.charAt(1) == '1'){
                            System.out.println("第三路开");
                        }else if (str.charAt(0) == '1'){
                            System.out.println("第四路开");
                        }else {
                            System.out.println("四路全关");
                        }
                        returnCode = "01";
                    }else{
                        JSONObject jsonObject = JSONUtil.parseObj(new String(data));
                        String number = jsonObject.getStr("number");
                        os.write("0666".getBytes());
                        if (ht.containsKey(number)){
                            vntThreadClient = ht.get(number);
                            System.out.println("下发指令连接："+vntThreadClient.toString());
                            os = vntThreadClient.getOutputStream();   //输出流
                            returnCode = jsonObject.getStr("returnCode");
                        }
                    }
                    //下发指令
                    os.write(ByteUtil.hexStr2Byte(returnCode));
//                    os.flush();
//                    os.close();
//                    if (vntThreadClient != null) {
//                        vntThreadClient.close();
//                    }
//                    //System.out.println(vntThreadClient);
//                    if ("shutdown".equals(vntThreadClient)) {
//                        break;
//                    }
                }
//                if (vntThreadClient != null) {
//                    vntThreadClient.close();
//                }
            }
//            if (vntThreadClient != null) {
//                vntThreadClient.close();
//            }
        } catch (Exception e) {
            e.printStackTrace();
            if (vntThreadClient != null) {
                vntThreadClient.close();
            }
        } finally {
//            if (os != null) {
//                os.flush();
//                os.close();
//            }
//            if (vntThreadClient != null) {
//                vntThreadClient.close();
//            }
        }
    }


    /**
     * 16进制 转 ASCII码
     * @param “3030313030312d30303300000000000000000000”
     * @return 001001-003
     */
    public static String convertHexToString(String hex) {

        StringBuilder sb = new StringBuilder();
        StringBuilder temp = new StringBuilder();

        //49204c6f7665204a617661 split into two characters 49, 20, 4c...
        for (int i = 0; i < hex.length() - 1; i += 2) {

            //grab the hex in pairs
            String output = hex.substring(i, (i + 2));
            if (!output.equals("00")) {
                //convert hex to decimal
                int decimal = Integer.parseInt(output, 16);
                //convert the decimal to character
                sb.append((char) decimal);

                temp.append(decimal);
            }
        }

        return sb.toString();

    }

    public static void main(String[] args) {

        System.out.println(convertHexToString("4A593435323034323239337258767267"));
        String str = Integer.toBinaryString(Integer.parseInt("00", 16));
        System.out.println(str);
        System.out.println(str.charAt(3));
        //FE010100619C
    }
}
